package com.fh.fruit.service.account.impl;

import com.fh.dao.DaoSupport;
import com.fh.fruit.entity.account.BalanceDetail;
import com.fh.fruit.entity.account.CashApply;
import com.fh.fruit.entity.account.UserAccount;
import com.fh.fruit.entity.account.UserReal;
import com.fh.fruit.service.account.AccountManager;
import com.fruit.sdk.account.NoticeManager;
import com.joe.utils.common.DateUtil;
import com.joe.utils.common.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author joe
 */
@Service
@Slf4j
public class AccountService implements AccountManager {
    protected static final DecimalFormat NUMFORMAT = new DecimalFormat("#.00");
    @Resource(name = "daoSupport")
    private DaoSupport dao;
    @Autowired
    private NoticeManager noticeManager;

    @Override
    public List<CashApply> listCashout(com.fh.entity.Page page) throws Exception {
        return (List<CashApply>) dao.findForList("AccountMapper.cashoutlistPage", page);
    }

    @Override
    public List<UserReal> listCert(com.fh.entity.Page page) throws Exception {
        return (List<UserReal>) dao.findForList("AccountMapper.certlistPage", page);
    }

    @Override
    public boolean checkCashout(long[] ids, String uid, String state, String remark) throws Exception {
        log.info("操作员{}{}id为{}的提现申请，备注为：{}", uid, "01".equals(state) ? "同意" : "拒绝", ids, remark);
        if (!("01".equals(state) || "02".equals(state)) || StringUtils.isEmpty(uid) || ids.length == 0) {
            log.warn("更新提现状态参数错误");
            return false;
        }

        Map<String, Object> map = new HashMap<>();
        map.put("uid", uid);
        map.put("state", state);
        map.put("remark", remark);
        map.put("time", DateUtil.getFormatDate(DateUtil.BASE));

        for (int i = 0; i < ids.length; i++) {
            map.put("id", ids[i]);
            int result1 = (int) dao.update("AccountMapper.updateCashout", map);

            map.clear();
            map.put("id", ids[i]);
            if ("01".equals(state)) {
                map.put("state", "03");
            }else{
                map.put("state", "02");
            }

            int result2 = (int) dao.update("AccountMapper.updateTrans", map);

            if (result1 > 0 ^ result2 > 0) {
                log.error("更新状态异常，更新提现的状态为{}；更新流水表的状态为", result1, result2);
                throw new RuntimeException("更新状态异常，更新提现的状态为" + result1 + "；更新流水表的状态为" + result2);
            }

            if (result1 <= 0) {
                log.warn("id为{}的提现申请不存在，忽略", ids[i]);
            } else {
                map.clear();
                log.debug("开始处理提现申请：{}", ids[i]);
                map.put("isTranId", false);
                map.put("id", ids[i]);
                CashApply cashApply = (CashApply) dao.findForObject("AccountMapper.getCashout", map);
                //通知
                String time = DateUtil.getFormatDate("MM月dd日", DateUtil.parse(cashApply.getCreate_time(),
                        DateUtil.BASE));
                String count = dealDouble(cashApply.getPrice().add(cashApply.getPoundage()));

                if ("02".equals(state)) {
                    log.debug("操作是拒绝，开始处理用户账户");
                    //如果是拒绝需要更新用户钱包，给用户钱包加上响应的处理
                    try {
                        map.clear();
                        map.put("uid", cashApply.getUser_id());
                        map.put("lock", true);
                        UserAccount account = (UserAccount) dao.findForObject("AccountMapper.getUserAccount", map);
                        log.debug("开始处理账户：{}，同时生成明细", account);
                        //拒绝提现，给用户钱包加上相应的钱，同时生成明细
                        account.setBalance(account.getBalance().add(cashApply.getPrice()).add(cashApply.getPoundage()));
                        int update = (int) dao.update("AccountMapper.updateByUserId", account);
                        log.debug("用户钱包{}更新{}", account, update > 0 ? "成功" : "失败");
                        createBalanceDetail(cashApply, account, false);
                        log.debug("账户、明细处理完毕");


                        try {
                            noticeManager.rejectCashout(cashApply.getUser_id(), count, time, cashApply.getCash_mode(),
                                    remark);
                        } catch (Exception e) {
                            log.error("提现{}通知失败", ids[i], e);
                        }
                    } catch (Exception e) {
                        log.debug("提现申请{}更新失败", ids, e);
                        throw new RuntimeException(e);
                    }
                } else {
                    try {
                        log.debug("提现{}通过，开始进行通知", ids[i]);
                        Map<String, Long> param = new HashMap<>();
                        param.put("transId", cashApply.getTransaction_id());
                        BigDecimal bigDecimal = (BigDecimal) dao.findForObject("AccountMapper.getBalance", param);

                        String way;
                        if (!StringUtils.isEmpty(cashApply.getAlipay_account())) {
                            //支付宝
                            String account = cashApply.getAlipay_account();
                            way = "支付宝(" + account.substring(0, 3) + "****" + account.substring(account.length() - 4)
                                    + ")";
                        } else {
                            //银行卡
                            String card = cashApply.getBank_card();
                            way = cashApply.getBank_name() + "(" + card.substring(0, 4) + "****" + card.substring(card
                                    .length() - 4) + ")";
                        }

                        noticeManager.allowCashout(cashApply.getUser_id(), way, dealDouble
                                (bigDecimal), count);
                    } catch (Exception e) {
                        log.error("提现{}通知失败", ids[i], e);
                    }
                }
            }
        }

        return true;
    }

    @Override
    public boolean checkCert(long[] ids, String uid, String state, String remark) throws Exception {
        log.info("操作员{}{}id为{}的实名认证申请，备注为：{}", uid, "01".equals(state) ? "同意" : "拒绝", ids, remark);
        if (!("03".equals(state) || "02".equals(state)) || StringUtils.isEmpty(uid) || ids.length == 0) {
            log.warn("审核实名认证参数错误");
            return false;
        }

        Map<String, Object> map = new HashMap<>();
        map.put("state", state);
        map.put("remark", remark);

        for (int i = 0; i < ids.length; i++) {
            map.put("id", ids[i]);
            int result = (int) dao.update("AccountMapper.updateCertification", map);
            if (result <= 0) {
                log.warn("id为{}的实名认证申请不存在，忽略", ids[i]);
            } else {
                try {
                    map.clear();
                    map.put("id", ids[i]);
                    Long noticeUid = (Long) dao.findForObject("AccountMapper.getUidFromCert", map);
                    log.debug("实名认证{}已审核，开始通知用户{}", ids[i], noticeUid);
                    if ("02".equals(state)) {
                        noticeManager.allowCert(noticeUid);
                    } else {
                        noticeManager.rejectCert(noticeUid);
                    }
                } catch (Exception e) {
                    log.error("实名认证{}通知失败", ids[i], e);
                }
            }
        }

        //需要通知用户
        return true;
    }


    /**
     * 将系统状态转换为数据库实名认证审核状态
     *
     * @param state 系统中的实名认证审核状态（2表示申请认证未审核，3表示实名认证审核未通过，4表
     *              示实名认证审核已通过，5表示未知状态）
     * @return 对应的数据库中的审核状态
     */
    protected String stateConvert(int state) {
        switch (state) {
            case 2:
                return "01";
            case 3:
                return "03";
            case 4:
                return "02";
            default:
                throw new RuntimeException("系统实名认证状态中没有状态：" + state);
        }
    }

    /**
     * 生成交易明细并保存（该方法已经保存）
     *
     * @param cashApply 提现申请
     * @param account   用户账户（更新后的账户，主要使用余额）
     * @param add       拒绝提现还是申请提现，false为拒绝提现，true为提现申请
     * @return 交易明细
     */
    private BalanceDetail createBalanceDetail(CashApply cashApply, UserAccount account, boolean add) {
        log.debug("根据提现申请{}和用户账户{}生成交易明细", cashApply, account);
        BalanceDetail balanceDetail = new BalanceDetail();
        BigDecimal all = cashApply.getPoundage().add(cashApply.getPrice());
        balanceDetail.setUserId((int) cashApply.getUser_id());
        balanceDetail.setMoney(all);
        balanceDetail.setTransactionId(cashApply.getTransaction_id());
        balanceDetail.setType("02");
        balanceDetail.setCreateTime(DateUtil.getFormatDate("yyyy-MM-dd HH:mm:ss"));
        balanceDetail.setUpdateTime(balanceDetail.getCreateTime());
        balanceDetail.setCurBalance(account.getBalance());

        if (add) {
            //同意提现
            balanceDetail.setRemark("提现申请");
            balanceDetail.setIncomeState("00");
        } else {
            //拒绝提现
            balanceDetail.setRemark("拒绝提现");
            balanceDetail.setIncomeState("01");
        }
        try {
            dao.batchSave("BalanceDetailMapper.insertBalanceDetails", Collections.singletonList(balanceDetail));
        } catch (Exception e) {
            log.error("插入提现申请失败", e);
            throw new RuntimeException(e);
        }
        log.info("交易明细保存成功，明细为：{}", balanceDetail);
        return balanceDetail;
    }

    /**
     * 将BigDecimal做保留小数点后两位处理，不足的补零（四舍五入）
     *
     * @param bigDecimal bigDecimal
     * @return 处理后的字符串
     */
    protected String dealDouble(BigDecimal bigDecimal) {
        double count = bigDecimal.doubleValue();
        if (count < 0.005 && count > -0.005) {
            return "0.00";
        }
        String result = NUMFORMAT.format(count);
        return result.startsWith(".") ? "0" + result : result;
    }
}
